#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>

#include <Windows.h>

#ifdef Q_OS_WIN
#include <Windows.h>
#include <QString>
#endif

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

   ui->label->setScaledContents(true);
    hat_net = cv::dnn::readNet("yolov3.weights", "yolov3.cfg");

    //CPU
  //  hat_net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
 //  hat_net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);


   //CUDA
   hat_net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
   hat_net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
   QMap<int,QString>classNames;
   classNames.insert(0, "人物");
   classNames.insert(56, "椅子");
   classNames.insert(66, "键盘");
   classNames.insert(67, "手机");

  for (auto it = classNames.begin(); it != classNames.end(); ++it) {
      this->ui->comboBox->addItem(it.value(), it.key());  // value 是显示的文本，key 是存储在 userData 中
  }



}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{

    capture = new cv::VideoCapture(this->ui->lineEdit->text().toStdString());
          if (!capture->isOpened()) {
              qDebug() << "无法打开RTSP流!";
          }
                timer = new QTimer(this);
                     connect(timer, &QTimer::timeout, this, &MainWindow::updateFrame);
                     timer->start(30);  // 每30ms更新一次画面（大约33帧每秒）

}
void MainWindow::updateFrame(){

            if (!capture || !capture->isOpened()) {
                return;
            }

            cv::UMat uframe;
            *capture >> uframe;  // 捕获一帧

            if (uframe.empty()) {
                return;  // 如果帧为空，直接返回
            }

            cv::Mat frame = uframe.getMat(cv::ACCESS_RW);
            // 转换BGR格式的OpenCV Mat到RGB格式
            cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);

            // 将OpenCV的Mat转换为QImage
            QImage img((const uchar*)frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
//            if (frameCounter >= 33) {
//                    img=  detectHatInImage(frame);
//                    frameCounter = 0;  // 重置计数器
//            }
             img=  detectHatInImage(frame);

            // 显示图片
            this->ui->label->setPixmap(QPixmap::fromImage(img));
}


bool MainWindow::detectHat(const cv::Mat& image, cv::dnn::Net& hat_net, std::vector<cv::Rect>& detectedBoxes,std::map<int, int>& detectedClasses) {
    cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(416, 416), cv::Scalar(0, 0, 0), true, false);
    hat_net.setInput(blob);

    std::vector<cv::Mat> outputs;
    hat_net.forward(outputs, hat_net.getUnconnectedOutLayersNames());

    for (const auto& output : outputs) {
        float* data = (float*)output.data;
        for (int j = 0; j < output.rows; ++j, data += output.cols) {
            float confidence = data[4];
            if (confidence > 0.5) { // 置信度阈值


                int class_id = std::max_element(data + 5, data + output.cols) - (data + 5);
               if (class_id == classId) { // 0 表示 "人" 类

                   // 计算框的坐标信息
                   int centerX = (int)(data[0] * image.cols);
                   int centerY = (int)(data[1] * image.rows);
                   int width = (int)(data[2] * image.cols);
                   int height = (int)(data[3] * image.rows);

                   // 计算矩形框的位置
                   int left = centerX - width / 2;
                   int top = centerY - height / 2;

                   // 保存检测到的框
                   detectedBoxes.push_back(cv::Rect(left, top, width, height));


               }





            }
        }
    }

    return !detectedBoxes.empty(); // 如果有检测，返回true
}

QImage MainWindow::detectHatInImage(const cv::Mat &image) {

    int64 start = cv::getTickCount();
    std::vector<cv::Rect> detectedBoxes;
    std::map<int, int> detectedClasses; // 保存每个类别的数量
    bool has_hat = detectHat(image, hat_net,detectedBoxes,detectedClasses);
    int64 end = cv::getTickCount();
     double duration = (end - start) / cv::getTickFrequency() * 1000; // 转换为毫秒
     qDebug()  << "Hat detection took: " << duration << " ms";
     if (has_hat) {
            for (const auto& box : detectedBoxes) {
                cv::rectangle(image, box, cv::Scalar(0, 255, 0), 2); // 绘制绿色矩形框
            }
            std::string str = "find";
            std::ostringstream oss;
            oss << str << " (" << duration << " ms)";
            cv::putText(image, oss.str(), cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
           // std::cout << "耗时: " << oss.str() << std::endl;

//            for (const auto& entry : detectedClasses) {
//                    std::cout << "类别 " << entry.first << ": " << entry.second << " 个框" << std::endl;
//                }


           // cv::imwrite("output_image.jpg", image);

        }
        else {
            qDebug()  << "没有检测到";
            cv::putText(image, "No find", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
        }
    // 将OpenCV的Mat转换为QImage
   QImage img((const uchar*)image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
    return img;

}


void MainWindow::on_pushButton_2_clicked()
{

  cv::Mat image = cv::imread("I:/yangshaodong/c++/test2/x64/test1.jpeg");
  cv::dnn::Net hat_net = cv::dnn::readNet("I:/yangshaodong/c++/test2/x64/Debug/yolov3.weights", "I:/yangshaodong/c++/test2/x64/Debug/yolov3.cfg");

  //CPU
//     hat_net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
//     hat_net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

     int64 start = cv::getTickCount();

     std::vector<cv::Rect> detectedBoxes;
       std::map<int, int> detectedClasses;
     bool has_hat = detectHat(image, hat_net, detectedBoxes,detectedClasses);

     int64 end = cv::getTickCount();
     double duration = (end - start) / cv::getTickFrequency() * 1000; // 转换为毫秒

     // 在图像上绘制框和文本
     if (has_hat) {
         for (const auto& box : detectedBoxes) {
             cv::rectangle(image, box, cv::Scalar(0, 255, 0), 2); // 绘制绿色矩形框
         }

         std::string str = "Hat Detected";
         std::ostringstream oss;
         oss << str << " (" << duration << " ms)";

         cv::putText(image, oss.str(), cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
         qDebug() << "耗时: " << QString::fromStdString(oss.str());
     }
     else {
         qDebug() << "没有";
         cv::putText(image, "No Hat", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
     }
}

void MainWindow::on_comboBox_currentIndexChanged(int index)
{
    classId = this->ui->comboBox->itemData(index).toInt();
}

void MainWindow::on_pushButton_3_clicked()
{


    capture = new cv::VideoCapture(this->ui->lineEdit_file->text().toStdString());
          if (!capture->isOpened()) {
              qDebug() << "无法打开RTSP流!";
          }
                timer = new QTimer(this);
                     connect(timer, &QTimer::timeout, this, &MainWindow::updateFrame);
                     timer->start(30);  // 每30ms更新一次画面（大约33帧每秒）


}

void MainWindow::on_pushButton_4_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(nullptr,
                                                          "选择文件",
                                                          QDir::currentPath(), // 初始路径
                                                          "项目文件 (*.mp4);;所有文件 (*)");
          if (!fileName.isEmpty()) {
              ui->lineEdit_file->setText(fileName);
          }
}




void MainWindow::on_pushButton_5_clicked()
{
 timer->stop();
 this->ui->label->setPixmap(QPixmap());
}
